package base.thread_example.example06;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * t1线程输出a， t2线程输出b， t3线程输出c，最终输出格式是：循环abc
 *
 * 采用 ReentrantLock 的 lock、unlock方式
 *
 */
public class LockUnlock {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition aCondition = lock.newCondition();//A 休息室
        Condition bCondition = lock.newCondition();//B 休息室
        Condition cCondition = lock.newCondition();//C 休息室

        ShareData2 sd = new ShareData2(lock, aCondition);

        new Thread(()->{
            while (true){
                try {
                    sd.print("a", aCondition, bCondition);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t1").start();

        new Thread(()->{
            while (true){
                try {
                    sd.print("b", bCondition, cCondition);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t2").start();

        new Thread(()->{
            while (true){
                try {
                    sd.print("c", cCondition, aCondition);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t3").start();
    }
}




class ShareData2 {
    private static final Logger log = LoggerFactory.getLogger(ShareData2.class);
    private ReentrantLock lock;
    private Condition currentCondition;

    public ShareData2(ReentrantLock lock, Condition currentCondition){
        this.lock = lock;
        this.currentCondition = currentCondition;
    }

    public void print(String s, Condition currentCondition, Condition nextCondition) throws InterruptedException {
        lock.lock();
        try {
            while (this.currentCondition != currentCondition){
                currentCondition.await();
            }
            log.info("{}:{}", Thread.currentThread().getName(), s);
            this.currentCondition = nextCondition;
            nextCondition.signalAll();
        }finally {
            lock.unlock();
        }
    }
}

